/**
 * @file main.c
 * @brief 嵌入式多媒体看板的主程序
 * @details
 * 该程序是整个系统的入口点，负责初始化硬件设备（LCD, 触摸屏）、加载资源、
 * 显示主菜单界面，并根据用户的触摸输入来启动不同的功能模块：
 * 1.  电子相册 (Photo Album)
 * 2.  电子书阅读器 (E-book Reader) with TTS
 * 3.  电子琴 (Piano) with Record/Playback
 *
 * 它使用 select() I/O多路复用模型来高效地处理用户输入，同时在空闲时
 * 更新UI（如时钟和相册预览），实现了一个非阻塞的事件驱动循环。
 * @version 2.0
 * @date 2025-07-10
 */

// --- C 标准库和系统库 ---
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>   // mmap, munmap
#include <sys/stat.h>
#include <dirent.h>     // opendir, readdir, closedir
#include <time.h>       // time, localtime, strftime, clock_gettime
#include <linux/input.h>// input_event
#include <sys/select.h> // select, fd_set
#include <errno.h>
#include <iconv.h>      // 字符编码转换
#include <math.h>       // 数学函数

// --- 第三方库 ---
#include "jpeglib.h"    // JPEG解码

// --- 自定义模块头文件 ---
#include "lcd.h"        // LCD底层绘图函数
#include "photo.h"      // 相册模块数据结构
#include "ts.h"         // 触摸屏驱动
#include "read.h"       // 电子书模块
#include "mp3.h"        // MP3播放模块
#include "ASC16.h"      // ASCII 8x16 点阵字库
#include "HZK16.h"      // 汉字 16x16 点阵字库
#include "tts_bridge.h" // 文本转语音(TTS) C语言桥接接口

// --- 函数前向声明 ---
void run_photo_album(int fd_ts);
void run_ebook(int fd_ts);
void run_piano(int fd_ts);
void draw_text(int x, int y, const char *text, int color);
void show_main_menu();
void update_dashboard_time();
char* gb2312_to_utf8(const char* input);
long get_time_in_us(void);

// ===================================================================
// 辅助函数区域
// ===================================================================

/**
 * @brief 使用iconv库将GB2312编码的字符串转换为UTF-8编码。
 * @details 电子书文件使用GB2312编码，而TTS引擎需要UTF-8编码的文本。
 * @param input 指向源GB2312编码字符串的指针。
 * @return char* 指向新分配的UTF-8字符串的指针，使用后需要手动free()。
 * 转换失败或输入为空则返回NULL。
 */
char* gb2312_to_utf8(const char* input) {
    if (input == NULL) return NULL;
    size_t input_len = strlen(input);
    if (input_len == 0) {
        char* empty_str = (char*)malloc(1);
        if (empty_str) empty_str[0] = '\0';
        return empty_str;
    }
    // 预估输出缓冲区大小，UTF-8最多可能占用GBK的3倍空间
    size_t output_len = input_len * 3 + 1;
    char* output_buffer = (char*)malloc(output_len);
    if (output_buffer == NULL) return NULL;

    char* in_ptr = (char*)input;
    char* out_ptr = output_buffer;
    size_t in_bytes_left = input_len;
    size_t out_bytes_left = output_len;

    // 打开一个从GB2312到UTF-8的转换描述符
    iconv_t cd = iconv_open("UTF-8", "GB2312");
    if (cd == (iconv_t)-1) {
        perror("iconv_open for UTF-8 <- GB2312");
        free(output_buffer);
        return NULL;
    }

    // 执行转换
    if (iconv(cd, &in_ptr, &in_bytes_left, &out_ptr, &out_bytes_left) == (size_t)-1) {
        perror("iconv conversion");
        free(output_buffer);
        iconv_close(cd);
        return NULL;
    }

    *out_ptr = '\0'; // 添加字符串结束符
    iconv_close(cd); // 关闭转换描述符
    return output_buffer;
}

/**
 * @brief 获取高精度 monotonic 时间（微秒）
 * @details 使用 CLOCK_MONOTONIC 可以保证时间是单调递增的，不受系统时间调整影响，
 * 非常适合用于测量时间间隔，例如在电子琴的录音和回放功能中。
 * @return long 当前的微秒时间戳。
 */
long get_time_in_us() {
    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
}


// --- 主菜单轮播功能的全局变量 ---
static char **album_files = NULL;       // 动态数组，存放图片文件路径
static int album_file_count = 0;        // 图片文件的总数
#define SLIDESHOW_INTERVAL 5            // 轮播间隔时间（秒）

/**
 * @brief 扫描图片目录并加载文件列表到全局变量中。
 * @details 采用两遍扫描法：第一遍统计文件数量以精确分配内存，第二遍读取并存储完整路径。
 * 这样可以避免使用动态数组调整大小的复杂性。
 */
void scan_album_files() {
    const char *dir = "./res/imagefiles";
    DIR *dp = opendir(dir);
    if (dp == NULL) {
        perror("opendir for slideshow");
        return;
    }

    // 第一遍扫描：计算文件数量
    album_file_count = 0;
    struct dirent *entry;
    while ((entry = readdir(dp)) != NULL) {
        if (strstr(entry->d_name, ".jpg") != NULL || strstr(entry->d_name, ".bmp") != NULL) {
            album_file_count++;
        }
    }
    closedir(dp);

    if (album_file_count == 0) return;

    // 根据文件数量分配指针数组的内存
    album_files = malloc(album_file_count * sizeof(char *));
    if (album_files == NULL) {
        perror("malloc for file list");
        album_file_count = 0;
        return;
    }

    // 第二遍扫描：分配内存并存储每个文件的完整路径
    dp = opendir(dir);
    int i = 0;
    while ((entry = readdir(dp)) != NULL && i < album_file_count) {
        if (strstr(entry->d_name, ".jpg") != NULL || strstr(entry->d_name, ".bmp") != NULL) {
            size_t path_len = strlen(dir) + strlen(entry->d_name) + 2; // +2 for '/' and '\0'
            album_files[i] = malloc(path_len);
            if (album_files[i] != NULL) {
                snprintf(album_files[i], path_len, "%s/%s", dir, entry->d_name);
                i++;
            }
        }
    }
    closedir(dp);
    album_file_count = i; // 最终确认成功加载的数量
}

/**
 * @brief 单独绘制/更新相册卡片预览区，用于主菜单的图片轮播。
 * @details 为了提高效率，这个函数只重绘相册卡片中的预览区域，而不是整个屏幕，
 * 避免了主循环中不必要的闪烁和性能开销。
 * @param image_path 要显示的图片的路径。如果为NULL或无效，则显示提示信息。
 */
void draw_album_preview(const char *image_path) {
    // --- 定义卡片和预览区的尺寸及颜色 ---
    #define CARD_W 210
    #define CARD_H 350
    #define CARD_Y 80
    #define CARD1_X 50
    #define MENU_CARD_BG_COLOR  0x00212F3D

    // 定义预览图的视口（viewport）
    int thumb_x = CARD1_X + 10, thumb_y = CARD_Y + 60, thumb_w = CARD_W - 20, thumb_h = CARD_H - 80;

    // 先用背景色清空预览区域，防止新旧图片叠加产生视觉错误
    lcd_draw_rect(thumb_x, thumb_y, thumb_w, thumb_h, MENU_CARD_BG_COLOR);

    // 检查图片路径是否有效
    if (image_path != NULL && access(image_path, F_OK) == 0) {
        // 根据文件后缀调用相应的缩放绘制函数
        if (strstr(image_path, ".bmp")) {
            draw_bmp_with_scale(image_path, 1.0, 0, 0, thumb_x, thumb_y, thumb_w, thumb_h);
        } else if (strstr(image_path, ".jpg")) {
            draw_jpeg_with_scale(image_path, 1.0, 0, 0, thumb_x, thumb_y, thumb_w, thumb_h);
        }
    } else {
        // 如果没有图片或路径无效，显示提示文字
        int text_x = CARD1_X + (CARD_W - 6*8)/2;
        int text_y = CARD_Y + CARD_H/2;
        draw_text(text_x, text_y, "No Img", 0xFFFFFF);
    }
}

// ===================================================================
// UI绘制函数
// ===================================================================

/**
 * @brief 更新主菜单右上角的时间显示。
 * @details 同样是为了效率，只重绘时间区域。
 */
void update_dashboard_time() {
    #define TIME_TOP_BAR_COLOR  0x00283747
    #define TIME_TEXT_COLOR     0xFFE0E0E0
    time_t t = time(NULL);
    struct tm *local = localtime(&t);
    char time_str[10];
    char date_str[12];

    // 格式化时间和日期字符串
    strftime(time_str, sizeof(time_str), "%H:%M:%S", local);
    strftime(date_str, sizeof(date_str), "%Y-%m-%d", local);

    // 绘制背景和文字
    lcd_draw_rect(600, 10, 190, 30, TIME_TOP_BAR_COLOR); // 清除旧时间
    draw_text(680, 10, date_str, TIME_TEXT_COLOR);
    draw_text(690, 28, time_str, TIME_TEXT_COLOR);
    #undef TIME_TOP_BAR_COLOR
    #undef TIME_TEXT_COLOR
}

/**
 * @brief 绘制主菜单的完整静态布局。
 * @details 这个函数负责绘制看板的背景、标题、三个功能卡片以及退出按钮。
 * 其中的汉字是通过直接访问HZK16点阵字库数据来绘制的。
 */
void show_main_menu() {
    // --- 定义UI颜色和尺寸宏，便于维护 ---
    #define MENU_BG_COLOR       0x001A2333
    #define MENU_TOP_BAR_COLOR  0x00283747
    #define MENU_CARD_BG_COLOR  0x00212F3D
    #define MENU_TEXT_COLOR     0xFFE0E0E0
    #define MENU_TITLE_COLOR    0xFFFFFFFF
    #define MENU_EXIT_BTN_COLOR 0x00C0392B
    #define CARD_W 210
    #define CARD_H 350
    #define CARD_Y 80
    #define CARD1_X 50
    #define CARD2_X 295
    #define CARD3_X 540

    // --- 1. 绘制背景和顶部栏 ---
    brush_lcd(MENU_BG_COLOR);
    lcd_draw_rect(0, 0, 800, 50, MENU_TOP_BAR_COLOR);
    
    // --- 2. 绘制标题 "多媒体看板" ---
    // 通过GB2312区位码计算公式: offset = ((区码-0xA1)*94 + (位码-0xA1)) * 32
    int title_x = 20, title_y = (50 - 16) / 2;
    draw_16x16(title_x, title_y, &szHZK16[32*(((unsigned char)0xB6-0xA1)*94 + ((unsigned char)0xE0-0xA1))], MENU_TITLE_COLOR); title_x += 16; // 多
    draw_16x16(title_x, title_y, &szHZK16[32*(((unsigned char)0xC3-0xA1)*94 + ((unsigned char)0xBD-0xA1))], MENU_TITLE_COLOR); title_x += 16; // 媒
    draw_16x16(title_x, title_y, &szHZK16[32*(((unsigned char)0xCC-0xA1)*94 + ((unsigned char)0xE5-0xA1))], MENU_TITLE_COLOR); title_x += 16; // 体
    draw_16x16(title_x, title_y, &szHZK16[32*(((unsigned char)0xBF-0xA1)*94 + ((unsigned char)0xB4-0xA1))], MENU_TITLE_COLOR); title_x += 16; // 看
    draw_16x16(title_x, title_y, &szHZK16[32*(((unsigned char)0xB0-0xA1)*94 + ((unsigned char)0xE5-0xA1))], MENU_TITLE_COLOR); // 板

    // --- 3. 绘制三个功能卡片的框架和标题 ---
    lcd_draw_rect(CARD1_X, CARD_Y, CARD_W, CARD_H, MENU_CARD_BG_COLOR);
    lcd_draw_rect(CARD2_X, CARD_Y, CARD_W, CARD_H, MENU_CARD_BG_COLOR);
    lcd_draw_rect(CARD3_X, CARD_Y, CARD_W, CARD_H, MENU_CARD_BG_COLOR);
    
    draw_16x16(CARD1_X + (CARD_W-4*16)/2, CARD_Y + 20, &szHZK16[32*(((unsigned char)0xB5-0xA1)*94+((unsigned char)0xE7-0xA1))], MENU_TEXT_COLOR); // 电
    draw_16x16(CARD1_X + (CARD_W-4*16)/2+16, CARD_Y + 20, &szHZK16[32*(((unsigned char)0xD7-0xA1)*94+((unsigned char)0xD3-0xA1))], MENU_TEXT_COLOR); // 子
    draw_16x16(CARD1_X + (CARD_W-4*16)/2+32, CARD_Y + 20, &szHZK16[32*(((unsigned char)0xCF-0xA1)*94+((unsigned char)0xE0-0xA1))], MENU_TEXT_COLOR); // 相
    draw_16x16(CARD1_X + (CARD_W-4*16)/2+48, CARD_Y + 20, &szHZK16[32*(((unsigned char)0xB2-0xA1)*94+((unsigned char)0xE1-0xA1))], MENU_TEXT_COLOR); // 册
    
    draw_16x16(CARD2_X + (CARD_W-3*16)/2, CARD_Y + 20, &szHZK16[32*(((unsigned char)0xB5-0xA1)*94+((unsigned char)0xE7-0xA1))], MENU_TEXT_COLOR); // 电
    draw_16x16(CARD2_X + (CARD_W-3*16)/2+16, CARD_Y + 20, &szHZK16[32*(((unsigned char)0xD7-0xA1)*94+((unsigned char)0xD3-0xA1))], MENU_TEXT_COLOR); // 子
    draw_16x16(CARD2_X + (CARD_W-3*16)/2+32, CARD_Y + 20, &szHZK16[32*(((unsigned char)0xCA-0xA1)*94+((unsigned char)0xE9-0xA1))], MENU_TEXT_COLOR); // 书

    draw_16x16(CARD3_X + (CARD_W-3*16)/2, CARD_Y + 20, &szHZK16[32*(((unsigned char)0xB5-0xA1)*94+((unsigned char)0xE7-0xA1))], MENU_TEXT_COLOR); // 电
    draw_16x16(CARD3_X + (CARD_W-3*16)/2+16, CARD_Y + 20, &szHZK16[32*(((unsigned char)0xD7-0xA1)*94+((unsigned char)0xD3-0xA1))], MENU_TEXT_COLOR); // 子
    draw_16x16(CARD3_X + (CARD_W-3*16)/2+32, CARD_Y + 20, &szHZK16[32*(((unsigned char)0xC7-0xA1)*94+((unsigned char)0xD9-0xA1))], MENU_TEXT_COLOR); // 琴

    // --- 4. 绘制退出按钮 ---
    lcd_draw_rect(700, 440, 80, 30, MENU_EXIT_BTN_COLOR);
    draw_16x16(700+(80-32)/2, 440+(30-16)/2, &szHZK16[32*(((unsigned char)0xCD-0xA1)*94+((unsigned char)0xCB-0xA1))], MENU_TITLE_COLOR); // 退
    draw_16x16(700+(80-32)/2+16, 440+(30-16)/2, &szHZK16[32*(((unsigned char)0xB3-0xA1)*94+((unsigned char)0xF6-0xA1))], MENU_TITLE_COLOR); // 出

    // --- 5. 绘制卡片动态内容 ---
    // 5.1 相册卡片: 显示第一张图片作为预览
    draw_album_preview((album_file_count > 0) ? album_files[0] : NULL);
    
    // 5.2 电子书卡片: 读取并显示上次阅读进度
    int last_chapter = -1, last_page = -1;
    FILE *ebook_state_file = fopen("./res/state/ebook_state.txt", "r");
    if (ebook_state_file != NULL) {
        fscanf(ebook_state_file, "%d %d", &last_chapter, &last_page);
        fclose(ebook_state_file);
    }
    if (last_chapter != -1) {
        int line1_y = CARD_Y + 160;
        int line2_y = CARD_Y + 190;
        int current_x = CARD2_X + (CARD_W - 5*16)/2;

        draw_16x16(current_x, line1_y, &szHZK16[32*(((unsigned char)0xC9-0xA1)*94+((unsigned char)0xCF-0xA1))], MENU_TEXT_COLOR); current_x+=16; // 上
        draw_16x16(current_x, line1_y, &szHZK16[32*(((unsigned char)0xB4-0xA1)*94+((unsigned char)0xCE -0xA1))], MENU_TEXT_COLOR); current_x+=16; // 次
        draw_16x16(current_x, line1_y, &szHZK16[32*(((unsigned char)0xD4-0xA1)*94+((unsigned char)0xC4-0xA1))], MENU_TEXT_COLOR); current_x+=16; // 阅
        draw_16x16(current_x, line1_y, &szHZK16[32*(((unsigned char)0xB6-0xA1)*94+((unsigned char)0xC1-0xA1))], MENU_TEXT_COLOR); current_x+=16; // 读
        draw_16x16(current_x, line1_y, &szHZK16[32*(((unsigned char)0xD6-0xA1)*94+((unsigned char)0xC1-0xA1))], MENU_TEXT_COLOR); // 至

        char num_buf[10];
        snprintf(num_buf, sizeof(num_buf), "%d", last_chapter + 1);
        int part1_len = 16 + strlen(num_buf)*8 + 16;
        snprintf(num_buf, sizeof(num_buf), "%d", last_page + 1);
        int part2_len = 16 + strlen(num_buf)*8 + 16;
        int total_width = part1_len + 16 + part2_len;
        current_x = CARD2_X + (CARD_W - total_width)/2;

        draw_16x16(current_x, line2_y, &szHZK16[32*(((unsigned char)0xB5-0xA1)*94+((unsigned char)0xDA-0xA1))], MENU_TEXT_COLOR); current_x+=16; // 第
        snprintf(num_buf, sizeof(num_buf), "%d", last_chapter + 1);
        draw_text(current_x, line2_y, num_buf, MENU_TEXT_COLOR); current_x += strlen(num_buf)*8;
        draw_16x16(current_x, line2_y, &szHZK16[32*(((unsigned char)0xD5-0xA1)*94+((unsigned char)0xC2-0xA1))], MENU_TEXT_COLOR); current_x+=16; // 章
        draw_text(current_x, line2_y, ", ", MENU_TEXT_COLOR); current_x+=16;

        draw_16x16(current_x, line2_y, &szHZK16[32*(((unsigned char)0xB5-0xA1)*94+((unsigned char)0xDA-0xA1))], MENU_TEXT_COLOR); current_x+=16; // 第
        snprintf(num_buf, sizeof(num_buf), "%d", last_page + 1);
        draw_text(current_x, line2_y, num_buf, MENU_TEXT_COLOR); current_x+=strlen(num_buf)*8;
        draw_16x16(current_x, line2_y, &szHZK16[32*(((unsigned char)0xD2-0xA1)*94+((unsigned char)0xB3-0xA1))], MENU_TEXT_COLOR); // 页

    } else {
        int text_x = CARD2_X + (CARD_W - 4*16)/2;
        int text_y = CARD_Y + 180;
        draw_16x16(text_x, text_y, &szHZK16[32*(((unsigned char)0xBF-0xA1)*94+((unsigned char)0xAA-0xA1))], MENU_TEXT_COLOR); text_x+=16; // 开
        draw_16x16(text_x, text_y, &szHZK16[32*(((unsigned char)0xCA-0xA1)*94+((unsigned char)0xBC-0xA1))], MENU_TEXT_COLOR); text_x+=16; // 始
        draw_16x16(text_x, text_y, &szHZK16[32*(((unsigned char)0xD4-0xA1)*94+((unsigned char)0xC4-0xA1))], MENU_TEXT_COLOR); text_x+=16; // 阅
        draw_16x16(text_x, text_y, &szHZK16[32*(((unsigned char)0xB6-0xA1)*94+((unsigned char)0xC1-0xA1))], MENU_TEXT_COLOR); // 读
    }
    
    // --- 5.3 绘制电子琴卡片: 绘制一个静态的钢琴键盘预览图 ---
    {
        int key_area_x = CARD3_X + 10;
        int key_area_y = CARD_Y + (CARD_H - 120) / 2 + 20;
        int key_area_w = CARD_W - 20;
        int key_area_h = 120;
        
        int white_key_color = 0x00FFFFFF;
        int black_key_color = 0x00333333;
        
        // 绘制7个白键
        int white_key_w = key_area_w / 7;
        for (int i = 0; i < 7; i++) {
            lcd_draw_rect(key_area_x + i * white_key_w, key_area_y, white_key_w - 1, key_area_h, white_key_color);
        }
        
        // 绘制5个黑键
        int black_key_w = white_key_w * 0.6;
        int black_key_h = key_area_h * 0.6;
        int black_key_positions[] = {0, 1, 3, 4, 5}; // 黑键在白键上的位置索引
        for (int i = 0; i < 5; i++) {
            int pos_idx = black_key_positions[i];
            int x_pos = key_area_x + (pos_idx + 1) * white_key_w - (black_key_w / 2);
            lcd_draw_rect(x_pos, key_area_y, black_key_w, black_key_h, black_key_color);
        }
    }
}

// ===================================================================
// 主函数: 程序入口
// ===================================================================
int main() {
    // --- 1. 初始化 ---
    printf("系统启动中...\n");

    // 初始化TTS SDK
    if (init_tts_sdk_c() != 0) {
        printf("警告: 无法初始化讯飞SDK，TTS功能将无法使用。\n");
    }

    // 打开并内存映射LCD设备
    int fd_lcd = open("/dev/ubuntu_lcd", O_RDWR);
    if (fd_lcd == -1) { perror("打开LCD设备失败"); return -1; }
    plcd = mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd_lcd, 0);
    if (plcd == MAP_FAILED) { perror("LCD内存映射失败"); close(fd_lcd); return -1; }

    // 打开触摸屏设备
    int fd_ts = open("/dev/ubuntu_event", O_RDONLY);
    if (fd_ts == -1) { perror("打开触摸屏设备失败"); munmap(plcd, 800*480*4); close(fd_lcd); return -1; }

    srand(time(NULL));      // 初始化随机数种子，用于图片轮播
    scan_album_files();     // 扫描图片文件并加载到内存

    printf("初始化完成，进入主循环。\n");

    // --- 2. 主事件循环 ---
    int needs_redraw = 1; // redraw标志，控制是否需要重绘整个屏幕
    time_t last_time_update = 0; // 上次更新时钟的时间
    time_t last_slideshow_time = time(NULL); // 上次轮播图片的时间

    while (1) {
        // 2.1 屏幕重绘逻辑
        if (needs_redraw) {
            show_main_menu(); // 绘制整个主菜单
            needs_redraw = 0;
            last_slideshow_time = time(NULL); // 重绘后重置轮播计时器
        }

        // 2.2 定时任务：每秒更新时钟
        time_t current_time = time(NULL);
        if (current_time != last_time_update) {
            update_dashboard_time();
            last_time_update = current_time;
        }

        // 2.3 定时任务：按间隔轮播图片
        if (current_time - last_slideshow_time >= SLIDESHOW_INTERVAL) {
            if (album_file_count > 0) {
                int random_index = rand() % album_file_count;
                draw_album_preview(album_files[random_index]); // 只更新相册卡片预览区
            }
            last_slideshow_time = current_time; // 更新计时器
        }

        // 2.4 I/O处理：使用 select 模型等待触摸输入
        // 这是事件循环的核心，它允许程序在没有触摸时执行其他任务（如更新时钟），
        // 而在有触摸时能立即响应，避免了使用 sleep() 或忙等待造成的资源浪费。
        fd_set readfds;
        FD_ZERO(&readfds);
        FD_SET(fd_ts, &readfds);
        struct timeval timeout;
        timeout.tv_sec = 0;
        timeout.tv_usec = 200000; // 设置200毫秒的超时
        
        int ret = select(fd_ts + 1, &readfds, NULL, NULL, &timeout);

        if (ret > 0 && FD_ISSET(fd_ts, &readfds)) {
            // 如果select返回大于0，说明触摸屏有数据可读
            struct postion pos;
            if (get_touch_event(fd_ts, &pos) == 1) { // 成功获取一个坐标
                // 判断触摸点在哪一个功能卡片或按钮上
                if (pos.y > 80 && pos.y < 430) { // 在三个主卡片区域内
                    if (pos.x > 50 && pos.x < 260)      { run_photo_album(fd_ts); needs_redraw = 1; }
                    else if (pos.x > 295 && pos.x < 505) { run_ebook(fd_ts);       needs_redraw = 1; }
                    else if (pos.x > 540 && pos.x < 750) { run_piano(fd_ts);       needs_redraw = 1; }
                }
                else if (pos.y > 440 && pos.x > 700) {
                    // 触摸了退出按钮
                    break; // 退出主循环
                }
            }
        }
        // 如果select返回0（超时）或-1（错误），则循环继续，执行下一次的定时任务检查。
    }

    // --- 3. 清理和退出 ---
    printf("程序退出中，正在清理资源...\n");

    // 释放为相册文件列表分配的内存
    if (album_files != NULL) {
        for (int i = 0; i < album_file_count; i++) {
            free(album_files[i]);
        }
        free(album_files);
    }
    
    brush_lcd(0x000000); // 黑屏
    munmap(plcd, 800 * 480 * 4); // 解除内存映射
    close(fd_lcd); // 关闭文件描述符
    close(fd_ts);
    uninit_tts_sdk_c(); // 反初始化TTS SDK
    
    printf("再见！\n");
    return 0;
}

// ===================================================================
// UI辅助函数
// ===================================================================
/**
 * @brief 在指定位置绘制一个ASCII字符串。
 * @param x 字符串左上角的X坐标。
 * @param y 字符串左上角的Y坐标。
 * @param text 要绘制的ASCII字符串。
 * @param color 颜色值。
 */
void draw_text(int x, int y, const char *text, int color) {
    int i = 0;
    while (text[i] != '\0') {
        // 简单的边界检查
        if (x + i * 8 < 800) {
            // 从ASC16字库中取出对应字符的点阵数据并绘制
            draw_8x16(x + i * 8, y, &szASC16[(unsigned char)text[i] * 16], color);
        }
        i++;
    }
}

// ===================================================================
// 模块一: 电子相册
// ===================================================================
void run_photo_album(int fd_ts) {
    Node *head = NULL;
    // 扫描图片目录，构建双向链表
    if (scanf_list("./res/imagefiles", &head) != 0 || head == NULL) {
        brush_lcd(0x008B0000); // 深红色背景
        draw_text(280, 230, "Error: No images found!", 0xFFFFFFFF);
        sleep(2);
        return;
    }
    Node *current_image = head;
    double zoom_factor = 1.0;
    int pan_offset_x = 0, pan_offset_y = 0;

    // --- 定义UI布局宏 ---
    #define ALBUM_INFO_BAR_H 40
    #define ALBUM_PANEL_X 640
    #define ALBUM_PANEL_W 160
    #define ALBUM_VIEWPORT_X 0
    #define ALBUM_VIEWPORT_Y ALBUM_INFO_BAR_H
    #define ALBUM_VIEWPORT_W (800 - ALBUM_PANEL_W)
    #define ALBUM_VIEWPORT_H (480 - ALBUM_INFO_BAR_H)
    #define ALBUM_BTN_RECT_W 140
    #define ALBUM_BTN_SQ_W 65
    #define ALBUM_BTN_H 40
    #define ALBUM_BTN_GAP 10
    #define ALBUM_BTN_X_RECT (ALBUM_PANEL_X + (ALBUM_PANEL_W - ALBUM_BTN_RECT_W) / 2)
    #define ALBUM_BTN_X_LEFT (ALBUM_PANEL_X + (ALBUM_PANEL_W - ALBUM_BTN_SQ_W * 2 - 10) / 2)
    #define ALBUM_BTN_X_RIGHT (ALBUM_BTN_X_LEFT + ALBUM_BTN_SQ_W + 10)
    #define ROW1_Y (ALBUM_VIEWPORT_Y + 15)
    #define ROW2_Y (ROW1_Y + ALBUM_BTN_H + ALBUM_BTN_GAP)
    #define ROW3_Y (ROW2_Y + ALBUM_BTN_H + ALBUM_BTN_GAP)
    #define ROW4_Y (ROW3_Y + ALBUM_BTN_H + ALBUM_BTN_GAP)
    #define ROW5_Y (ROW4_Y + ALBUM_BTN_H + ALBUM_BTN_GAP + 5)
    #define ROW6_Y (ROW5_Y + ALBUM_BTN_H + ALBUM_BTN_GAP)
    #define ROW7_Y (480 - ALBUM_BTN_H - 20)
    #define ALBUM_PANEL_BG_COLOR 0x00EEEEEE
    #define ALBUM_INFO_TEXT_COLOR 0x00333333
    #define ALBUM_BTN_NAV_COLOR 0x00A9A9A9
    #define ALBUM_BTN_ZOOM_COLOR 0x003498DB
    #define ALBUM_BTN_PAN_COLOR 0x001ABC9C
    #define ALBUM_BTN_BACK_COLOR 0x00C0392B
    #define ALBUM_BTN_TEXT_COLOR 0xFFFFFFFF

    int needs_redraw = 1;
    while (1) {
        if (needs_redraw) {
            // 1. 绘制背景和图片显示区
            brush_lcd(ALBUM_PANEL_BG_COLOR); // 绘制右侧面板背景
            lcd_draw_rect(ALBUM_VIEWPORT_X, ALBUM_VIEWPORT_Y, ALBUM_VIEWPORT_W, ALBUM_VIEWPORT_H, 0x00202020); // 绘制左侧图片视口背景

            // 2. 绘制顶部信息栏
            int info_text_y = (ALBUM_INFO_BAR_H - 16) / 2;
            int current_x = 20;
            draw_16x16(current_x, info_text_y, &szHZK16[32*(((unsigned char)0xCE -0xA1)*94 + ((unsigned char)0xC4-0xA1))], ALBUM_INFO_TEXT_COLOR); current_x += 16; // 文
            draw_16x16(current_x, info_text_y, &szHZK16[32*(((unsigned char)0xBC-0xA1)*94 + ((unsigned char)0xFE -0xA1))], ALBUM_INFO_TEXT_COLOR); current_x += 16; // 件
            draw_16x16(current_x, info_text_y, &szHZK16[32*(((unsigned char)0xC3-0xA1)*94 + ((unsigned char)0xFB-0xA1))], ALBUM_INFO_TEXT_COLOR); current_x += 16; // 名
            draw_text(current_x, info_text_y, ":", ALBUM_INFO_TEXT_COLOR); current_x += 16;
            const char *full_path = current_image->filename;
            const char *base_name = strrchr(full_path, '/'); // 从完整路径中提取文件名
            base_name = (base_name == NULL) ? full_path : base_name + 1;
            draw_text(current_x, info_text_y, base_name, ALBUM_INFO_TEXT_COLOR);
            
            current_x = 400;
            draw_16x16(current_x, info_text_y, &szHZK16[32*(((unsigned char)0xCB-0xA1)*94 + ((unsigned char)0xF5-0xA1))], ALBUM_INFO_TEXT_COLOR); current_x += 16; // 缩
            draw_16x16(current_x, info_text_y, &szHZK16[32*(((unsigned char)0xB7-0xA1)*94 + ((unsigned char)0xC5-0xA1))], ALBUM_INFO_TEXT_COLOR); current_x += 8; // 放
            draw_text(current_x, info_text_y, ":", ALBUM_INFO_TEXT_COLOR); current_x += 16;
            char zoom_str[10];
            snprintf(zoom_str, sizeof(zoom_str), "%d%%", (int)(zoom_factor * 100));
            draw_text(current_x, info_text_y, zoom_str, ALBUM_INFO_TEXT_COLOR);

            // 3. 绘制图片
            const char *filename = current_image->filename;
            if (strstr(filename, ".bmp")) { draw_bmp_with_scale(filename, zoom_factor, pan_offset_x, pan_offset_y, ALBUM_VIEWPORT_X, ALBUM_VIEWPORT_Y, ALBUM_VIEWPORT_W, ALBUM_VIEWPORT_H);
            } else if (strstr(filename, ".jpg") || strstr(filename, ".jpeg")) { draw_jpeg_with_scale(filename, zoom_factor, pan_offset_x, pan_offset_y, ALBUM_VIEWPORT_X, ALBUM_VIEWPORT_Y, ALBUM_VIEWPORT_W, ALBUM_VIEWPORT_H); }

            // 4. 绘制所有控制按钮
            lcd_draw_rect(ALBUM_BTN_X_RECT, ROW1_Y, ALBUM_BTN_RECT_W, ALBUM_BTN_H, ALBUM_BTN_NAV_COLOR);
            lcd_draw_rect(ALBUM_BTN_X_RECT, ROW2_Y, ALBUM_BTN_RECT_W, ALBUM_BTN_H, ALBUM_BTN_NAV_COLOR);
            lcd_draw_rect(ALBUM_BTN_X_RECT, ROW3_Y, ALBUM_BTN_RECT_W, ALBUM_BTN_H, ALBUM_BTN_ZOOM_COLOR);
            lcd_draw_rect(ALBUM_BTN_X_RECT, ROW4_Y, ALBUM_BTN_RECT_W, ALBUM_BTN_H, ALBUM_BTN_ZOOM_COLOR);
            lcd_draw_rect(ALBUM_BTN_X_LEFT, ROW5_Y, ALBUM_BTN_SQ_W, ALBUM_BTN_H, ALBUM_BTN_PAN_COLOR);
            lcd_draw_rect(ALBUM_BTN_X_RIGHT, ROW5_Y, ALBUM_BTN_SQ_W, ALBUM_BTN_H, ALBUM_BTN_PAN_COLOR);
            lcd_draw_rect(ALBUM_BTN_X_LEFT, ROW6_Y, ALBUM_BTN_SQ_W, ALBUM_BTN_H, ALBUM_BTN_PAN_COLOR);
            lcd_draw_rect(ALBUM_BTN_X_RIGHT, ROW6_Y, ALBUM_BTN_SQ_W, ALBUM_BTN_H, ALBUM_BTN_PAN_COLOR);
            lcd_draw_rect(ALBUM_BTN_X_RECT, ROW7_Y, ALBUM_BTN_RECT_W, ALBUM_BTN_H, ALBUM_BTN_BACK_COLOR);

            // 5. 绘制按钮上的文字
            int text_y_offset = (ALBUM_BTN_H - 16) / 2;
            int text_x_rect_3char = ALBUM_BTN_X_RECT + (ALBUM_BTN_RECT_W - 3 * 16) / 2;
            draw_16x16(text_x_rect_3char, ROW1_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xC9-0xA1)*94 + ((unsigned char)0xCF-0xA1))], ALBUM_BTN_TEXT_COLOR); // 上一张
            draw_16x16(text_x_rect_3char+16, ROW1_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xD2-0xA1)*94 + ((unsigned char)0xBB-0xA1))], ALBUM_BTN_TEXT_COLOR);
            draw_16x16(text_x_rect_3char+32, ROW1_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xD5-0xA1)*94 + ((unsigned char)0xC5-0xA1))], ALBUM_BTN_TEXT_COLOR);
            
            draw_16x16(text_x_rect_3char, ROW2_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xCF-0xA1)*94 + ((unsigned char)0xC2-0xA1))], ALBUM_BTN_TEXT_COLOR); // 下一张
            draw_16x16(text_x_rect_3char+16, ROW2_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xD2-0xA1)*94 + ((unsigned char)0xBB-0xA1))], ALBUM_BTN_TEXT_COLOR);
            draw_16x16(text_x_rect_3char+32, ROW2_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xD5-0xA1)*94 + ((unsigned char)0xC5-0xA1))], ALBUM_BTN_TEXT_COLOR);

            int text_x_rect_2char = ALBUM_BTN_X_RECT + (ALBUM_BTN_RECT_W - 2 * 16) / 2;
            draw_16x16(text_x_rect_2char, ROW3_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xB7-0xA1)*94 + ((unsigned char)0xC5-0xA1))], ALBUM_BTN_TEXT_COLOR); // 放大
            draw_16x16(text_x_rect_2char+16, ROW3_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xB4-0xA1)*94 + ((unsigned char)0xF3-0xA1))], ALBUM_BTN_TEXT_COLOR);
            
            draw_16x16(text_x_rect_2char, ROW4_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xCB-0xA1)*94 + ((unsigned char)0xF5-0xA1))], ALBUM_BTN_TEXT_COLOR); // 缩小
            draw_16x16(text_x_rect_2char+16, ROW4_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xD0-0xA1)*94 + ((unsigned char)0xA1-0xA1))], ALBUM_BTN_TEXT_COLOR);
            
            int text_x_sq_1char = (ALBUM_BTN_SQ_W - 1*16)/2;
            draw_16x16(ALBUM_BTN_X_LEFT + text_x_sq_1char, ROW5_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xC9-0xA1)*94 + ((unsigned char)0xCF-0xA1))], ALBUM_BTN_TEXT_COLOR); // 上
            draw_16x16(ALBUM_BTN_X_RIGHT + text_x_sq_1char, ROW5_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xCF-0xA1)*94 + ((unsigned char)0xC2-0xA1))], ALBUM_BTN_TEXT_COLOR); // 下
            draw_16x16(ALBUM_BTN_X_LEFT + text_x_sq_1char, ROW6_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xD7-0xA1)*94 + ((unsigned char)0xF3-0xA1))], ALBUM_BTN_TEXT_COLOR); // 左
            draw_16x16(ALBUM_BTN_X_RIGHT + text_x_sq_1char, ROW6_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xD3-0xA1)*94 + ((unsigned char)0xD2-0xA1))], ALBUM_BTN_TEXT_COLOR); // 右
            
            draw_16x16(text_x_rect_2char, ROW7_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xB7-0xA1)*94 + ((unsigned char)0xB5-0xA1))], ALBUM_BTN_TEXT_COLOR); // 返回
            draw_16x16(text_x_rect_2char+16, ROW7_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xBB-0xA1)*94 + ((unsigned char)0xD8-0xA1))], ALBUM_BTN_TEXT_COLOR);
            
            needs_redraw = 0;
        }

        // 使用select等待触摸输入
        fd_set readfds; struct timeval timeout; FD_ZERO(&readfds); FD_SET(fd_ts, &readfds);
        timeout.tv_sec = 0; timeout.tv_usec = 50000;
        int ret = select(fd_ts + 1, &readfds, NULL, NULL, &timeout);
        if (ret > 0 && FD_ISSET(fd_ts, &readfds)) {
            struct postion touch_pos;
            if (get_touch_event(fd_ts, &touch_pos) == 1) {
                int x = touch_pos.x; int y = touch_pos.y;
                if (x > ALBUM_PANEL_X) { // 触摸在右侧控制面板
                    if (y > ROW1_Y && y < ROW1_Y + ALBUM_BTN_H) { // 上一张
                        if (current_image->prev) { current_image = current_image->prev; zoom_factor=1.0; pan_offset_x=0; pan_offset_y=0; needs_redraw = 1; }
                    } else if (y > ROW2_Y && y < ROW2_Y + ALBUM_BTN_H) { // 下一张
                        if (current_image->next) { current_image = current_image->next; zoom_factor=1.0; pan_offset_x=0; pan_offset_y=0; needs_redraw = 1; }
                    } else if (y > ROW3_Y && y < ROW3_Y + ALBUM_BTN_H) { // 放大
                        if (zoom_factor < 4.0) { zoom_factor += 0.2; needs_redraw = 1; }
                    } else if (y > ROW4_Y && y < ROW4_Y + ALBUM_BTN_H) { // 缩小
                        if (zoom_factor > 0.2) { zoom_factor -= 0.2; needs_redraw = 1; }
                    } else if (y > ROW5_Y && y < ROW5_Y + ALBUM_BTN_H) { // 上下平移
                        if (x > ALBUM_BTN_X_LEFT && x < ALBUM_BTN_X_LEFT + ALBUM_BTN_SQ_W) { pan_offset_y -= 30; needs_redraw = 1; } // 上
                        else if (x > ALBUM_BTN_X_RIGHT && x < ALBUM_BTN_X_RIGHT + ALBUM_BTN_SQ_W) { pan_offset_y += 30; needs_redraw = 1; } // 下
                    } else if (y > ROW6_Y && y < ROW6_Y + ALBUM_BTN_H) { // 左右平移
                        if (x > ALBUM_BTN_X_LEFT && x < ALBUM_BTN_X_LEFT + ALBUM_BTN_SQ_W) { pan_offset_x -= 30; needs_redraw = 1; } // 左
                        else if (x > ALBUM_BTN_X_RIGHT && x < ALBUM_BTN_X_RIGHT + ALBUM_BTN_SQ_W) { pan_offset_x += 30; needs_redraw = 1; } // 右
                    } else if (y > ROW7_Y && y < ROW7_Y + ALBUM_BTN_H) { // 返回
                        // 释放链表内存
                        Node *p = head;
                        while(p != NULL) { Node *temp = p; p = p->next; free(temp); }
                        head = NULL;
                        return;
                    }
                }
            }
        }
    }
}

// ===================================================================
// 模块二: 电子书 (新增状态保存)
// ===================================================================
void run_ebook(int fd_ts) {
    long page_positions[100] = {0}; // 存储每页起始位置在文件中的偏移量
    int current_page = 0, current_chapter = 0;
    char filepath[256];

    snprintf(filepath, sizeof(filepath), "./res/novel/%s", chapters[current_chapter]);
    FILE *fp = fopen(filepath, "r");
    if (fp == NULL) { perror("fopen ebook file error"); brush_lcd(0x008B0000); draw_text(250, 230, "Error: Cannot open novel file!", 0xFFFFFFFF); sleep(2); return; }
    
    int needs_redraw = 1;
    // --- 定义UI布局宏 ---
    #define EBOOK_PANEL_X 640
    #define EBOOK_PANEL_W 160
    #define EBOOK_BTN_W 140
    #define EBOOK_BTN_H 50
    #define EBOOK_BTN_X (EBOOK_PANEL_X + (EBOOK_PANEL_W - EBOOK_BTN_W) / 2)
    #define EBOOK_BTN_GAP 18
    #define EBOOK_BTN_PREV_PAGE_Y 20
    #define EBOOK_BTN_NEXT_PAGE_Y (EBOOK_BTN_PREV_PAGE_Y + EBOOK_BTN_H + EBOOK_BTN_GAP)
    #define EBOOK_BTN_PREV_CHAP_Y (EBOOK_BTN_NEXT_PAGE_Y + EBOOK_BTN_H + EBOOK_BTN_GAP)
    #define EBOOK_BTN_NEXT_CHAP_Y (EBOOK_BTN_PREV_CHAP_Y + EBOOK_BTN_H + EBOOK_BTN_GAP)
    #define EBOOK_BTN_TTS_Y (EBOOK_BTN_NEXT_CHAP_Y + EBOOK_BTN_H + EBOOK_BTN_GAP)
    #define EBOOK_BTN_BACK_Y (480 - EBOOK_BTN_H - 20)
    #define EBOOK_PANEL_BG_COLOR 0x00EEEEEE
    #define EBOOK_BTN_TTS_Y (EBOOK_BTN_NEXT_CHAP_Y + EBOOK_BTN_H + EBOOK_BTN_GAP)
    #define EBOOK_BTN_BACK_Y (480 - EBOOK_BTN_H - 20)
    #define EBOOK_PANEL_BG_COLOR 0x00EEEEEE
    #define EBOOK_BTN_NORMAL_COLOR 0x00A9A9A9
    #define EBOOK_BTN_TTS_COLOR 0x0028B463
    #define EBOOK_BTN_BACK_COLOR 0x00C0392B
    #define EBOOK_BTN_TEXT_COLOR 0xFFFFFFFF

    while(1) {
        if (needs_redraw) {
            // 1. 绘制背景和右侧面板
            brush_lcd(0xffffff); // 文本区白色背景
            lcd_draw_rect(EBOOK_PANEL_X, 0, EBOOK_PANEL_W, 480, EBOOK_PANEL_BG_COLOR);
            
            // 2. 绘制所有按钮
            lcd_draw_rect(EBOOK_BTN_X, EBOOK_BTN_PREV_PAGE_Y, EBOOK_BTN_W, EBOOK_BTN_H, EBOOK_BTN_NORMAL_COLOR);
            lcd_draw_rect(EBOOK_BTN_X, EBOOK_BTN_NEXT_PAGE_Y, EBOOK_BTN_W, EBOOK_BTN_H, EBOOK_BTN_NORMAL_COLOR);
            lcd_draw_rect(EBOOK_BTN_X, EBOOK_BTN_PREV_CHAP_Y, EBOOK_BTN_W, EBOOK_BTN_H, EBOOK_BTN_NORMAL_COLOR);
            lcd_draw_rect(EBOOK_BTN_X, EBOOK_BTN_NEXT_CHAP_Y, EBOOK_BTN_W, EBOOK_BTN_H, EBOOK_BTN_NORMAL_COLOR);
            lcd_draw_rect(EBOOK_BTN_X, EBOOK_BTN_TTS_Y, EBOOK_BTN_W, EBOOK_BTN_H, EBOOK_BTN_TTS_COLOR);
            lcd_draw_rect(EBOOK_BTN_X, EBOOK_BTN_BACK_Y, EBOOK_BTN_W, EBOOK_BTN_H, EBOOK_BTN_BACK_COLOR);
            
            // 3. 绘制按钮上的文字
            int text_y_offset = (EBOOK_BTN_H - 16) / 2;
            int text_x_3char = EBOOK_BTN_X + (EBOOK_BTN_W - 3 * 16) / 2;
            draw_16x16(text_x_3char, EBOOK_BTN_PREV_PAGE_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xC9-0xA1)*94 + ((unsigned char)0xCF-0xA1))], EBOOK_BTN_TEXT_COLOR); // 上一页
            draw_16x16(text_x_3char+16, EBOOK_BTN_PREV_PAGE_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xD2-0xA1)*94 + ((unsigned char)0xBB-0xA1))], EBOOK_BTN_TEXT_COLOR);
            draw_16x16(text_x_3char+32, EBOOK_BTN_PREV_PAGE_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xD2-0xA1)*94 + ((unsigned char)0xB3-0xA1))], EBOOK_BTN_TEXT_COLOR);
            draw_16x16(text_x_3char, EBOOK_BTN_NEXT_PAGE_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xCF-0xA1)*94 + ((unsigned char)0xC2-0xA1))], EBOOK_BTN_TEXT_COLOR); // 下一页
            draw_16x16(text_x_3char+16, EBOOK_BTN_NEXT_PAGE_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xD2-0xA1)*94 + ((unsigned char)0xBB-0xA1))], EBOOK_BTN_TEXT_COLOR);
            draw_16x16(text_x_3char+32, EBOOK_BTN_NEXT_PAGE_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xD2-0xA1)*94 + ((unsigned char)0xB3-0xA1))], EBOOK_BTN_TEXT_COLOR);
            draw_16x16(text_x_3char, EBOOK_BTN_PREV_CHAP_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xC9-0xA1)*94 + ((unsigned char)0xCF-0xA1))], EBOOK_BTN_TEXT_COLOR); // 上一章
            draw_16x16(text_x_3char+16, EBOOK_BTN_PREV_CHAP_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xD2-0xA1)*94 + ((unsigned char)0xBB-0xA1))], EBOOK_BTN_TEXT_COLOR);
            draw_16x16(text_x_3char+32, EBOOK_BTN_PREV_CHAP_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xD5-0xA1)*94 + ((unsigned char)0xC2-0xA1))], EBOOK_BTN_TEXT_COLOR);
            draw_16x16(text_x_3char, EBOOK_BTN_NEXT_CHAP_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xCF-0xA1)*94 + ((unsigned char)0xC2-0xA1))], EBOOK_BTN_TEXT_COLOR); // 下一章
            draw_16x16(text_x_3char+16, EBOOK_BTN_NEXT_CHAP_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xD2-0xA1)*94 + ((unsigned char)0xBB-0xA1))], EBOOK_BTN_TEXT_COLOR);
            draw_16x16(text_x_3char+32, EBOOK_BTN_NEXT_CHAP_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xD5-0xA1)*94 + ((unsigned char)0xC2-0xA1))], EBOOK_BTN_TEXT_COLOR);
            
            int text_x_2char = EBOOK_BTN_X + (EBOOK_BTN_W - 2 * 16) / 2;
            draw_16x16(text_x_2char, EBOOK_BTN_TTS_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xCC-0xA1)*94 + ((unsigned char)0xFD-0xA1))], EBOOK_BTN_TEXT_COLOR); // 听书
            draw_16x16(text_x_2char+16, EBOOK_BTN_TTS_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xCA-0xA1)*94 + ((unsigned char)0xE9-0xA1))], EBOOK_BTN_TEXT_COLOR);
            draw_16x16(text_x_2char, EBOOK_BTN_BACK_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xB7-0xA1)*94 + ((unsigned char)0xB5-0xA1))], EBOOK_BTN_TEXT_COLOR); // 返回
            draw_16x16(text_x_2char+16, EBOOK_BTN_BACK_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xBB-0xA1)*94 + ((unsigned char)0xD8-0xA1))], EBOOK_BTN_TEXT_COLOR);

            // 4. 显示当前页的文本
            fseek(fp, page_positions[current_page], SEEK_SET);
            show_page(fp);
            needs_redraw = 0;
        }

        // 等待触摸输入
        fd_set readfds; FD_ZERO(&readfds); FD_SET(fd_ts, &readfds);
        struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 50000;
        int ret = select(fd_ts + 1, &readfds, NULL, NULL, &timeout);
        if (ret > 0 && FD_ISSET(fd_ts, &readfds)) {
            struct postion pos;
            if (get_touch_event(fd_ts, &pos) == 1) {
                if (pos.x > EBOOK_PANEL_X) { // 触摸在右侧控制面板
                    if (pos.y > EBOOK_BTN_BACK_Y && pos.y < EBOOK_BTN_BACK_Y + EBOOK_BTN_H) { // 返回按钮
                        // 保存当前阅读进度
                        FILE *state_file = fopen("./res/state/ebook_state.txt", "w");
                        if (state_file != NULL) { fprintf(state_file, "%d %d", current_chapter, current_page); fclose(state_file); }
                        system("killall mpg123 > /dev/null 2>&1"); // 停止可能在播放的TTS音频
                        fclose(fp);
                        return;
                    } else if (pos.y > EBOOK_BTN_PREV_PAGE_Y && pos.y < EBOOK_BTN_PREV_PAGE_Y + EBOOK_BTN_H) { // 上一页
                        if (current_page > 0) { current_page--; needs_redraw = 1; }
                    } else if (pos.y > EBOOK_BTN_NEXT_PAGE_Y && pos.y < EBOOK_BTN_NEXT_PAGE_Y + EBOOK_BTN_H) { // 下一页
                        page_positions[current_page + 1] = ftell(fp); // 记录下一页的起始位置
                        int check = fgetc(fp); // 检查是否已到文件末尾
                        if (check == EOF) { // 如果是最后一页
                            // 可以选择翻到下一章或提示已是末尾
                            // 这里简单地回到本章开头
                            rewind(fp); current_page = 0; memset(page_positions, 0, sizeof(page_positions));
                        } else { 
                            ungetc(check, fp); // 将读出的字符放回流中
                            current_page++; 
                        }
                        needs_redraw = 1;
                    } else if (pos.y > EBOOK_BTN_PREV_CHAP_Y && pos.y < EBOOK_BTN_PREV_CHAP_Y + EBOOK_BTN_H) { // 上一章
                        if (current_chapter > 0) {
                            current_chapter--; fclose(fp); snprintf(filepath, sizeof(filepath), "./res/novel/%s", chapters[current_chapter]);
                            fp = fopen(filepath, "r"); if (fp == NULL) { return; } // 打开新章节文件
                            current_page = 0; memset(page_positions, 0, sizeof(page_positions)); needs_redraw = 1;
                        }
                    } else if (pos.y > EBOOK_BTN_NEXT_CHAP_Y && pos.y < EBOOK_BTN_NEXT_CHAP_Y + EBOOK_BTN_H) { // 下一章
                        if (current_chapter < sizeof(chapters) / sizeof(chapters[0]) - 1) {
                            current_chapter++; fclose(fp); snprintf(filepath, sizeof(filepath), "./res/novel/%s", chapters[current_chapter]);
                            current_chapter++; fclose(fp); snprintf(filepath, sizeof(filepath), "./res/novel/%s", chapters[current_chapter]);
                            fp = fopen(filepath, "r"); if (fp == NULL) { return; }
                            current_page = 0; memset(page_positions, 0, sizeof(page_positions)); needs_redraw = 1;
                        }
                    } else if (pos.y > EBOOK_BTN_TTS_Y && pos.y < EBOOK_BTN_TTS_Y + EBOOK_BTN_H) { // 听书按钮
                        char page_text_buffer[2048] = {0};
                        long original_pos = ftell(fp); // 保存当前文件指针位置
                        fseek(fp, page_positions[current_page], SEEK_SET); // 定位到本页开头
                        
                        // 读取当前页的文本内容到缓冲区
                        {
                            int lines_read = 0; char line_buf[81]; int current_len = 0; page_text_buffer[0] = '\0';
                            while(lines_read < 30 && fgets(line_buf, sizeof(line_buf), fp) != NULL) {
                                size_t line_len = strlen(line_buf);
                                if (line_len > 0 && line_buf[line_len - 1] == '\n') { line_buf[line_len - 1] = '\0'; line_len--; }
                                if (current_len + line_len < sizeof(page_text_buffer) - 2) { 
                                    strcat(page_text_buffer, line_buf); 
                                    strcat(page_text_buffer, " "); // 用空格连接行
                                    current_len += line_len + 1;
                                } else { break; }
                                lines_read++;
                            }
                        }
                        fseek(fp, original_pos, SEEK_SET); // 恢复文件指针

                        if (strlen(page_text_buffer) > 0) {
                            printf("获取到的原始GB2312文本: %s\n", page_text_buffer);
                            char* utf8_text = gb2312_to_utf8(page_text_buffer); // 编码转换
                            if (utf8_text != NULL) {
                                printf("转换后的UTF-8文本: %s\n", utf8_text);
                                if (text_to_speech_c(utf8_text, "./res/audio/tts_output.mp3") == 0) {
                                    printf("语音合成成功, 准备播放。\n");
                                    system("killall mpg123 > /dev/null 2>&1"); // 停止之前的播放
                                    system("mpg123 -q -o alsa ./res/audio/tts_output.mp3 &"); // 后台播放
                                } else { printf("语音合成失败！\n"); }
                                free(utf8_text);
                            } else { printf("编码转换失败！\n"); }
                        }
                    }
                }
            }
        }
    }
}

// ===================================================================
// 模块三: 电子琴
// ===================================================================
void run_piano(int fd_ts) {
    // 定义钢琴的状态：空闲、录音中、回放中
    enum PianoState { P_IDLE, P_RECORDING, P_PLAYBACK };
    // 定义一个音符事件结构体，包含按键索引和与上一音符的延迟（微秒）
    struct NoteEvent { int key_index; long delay_us; };
    #define MAX_NOTES 500
    
    // --- 状态变量 ---
    enum PianoState current_state = P_IDLE;
    struct NoteEvent recorded_song[MAX_NOTES];
    int note_count = 0;
    long key_release_times[12] = {0}; // 用于按键动画，记录每个按键应恢复正常状态的时间
    long next_note_play_time = 0;     // 回放时，下一个音符应被播放的时间点
    long last_record_time = 0;        // 录音时，上一个音符被记录的时间点
    int playback_index = 0;           // 回放时，当前播放到第几个音符

    // --- UI宏定义 ---
    #define PIANO_PANEL_H 80
    #define PIANO_PANEL_Y (480 - PIANO_PANEL_H)
    #define PIANO_BTN_H 50
    #define PIANO_BTN_W 140
    #define PIANO_BTN_Y (PIANO_PANEL_Y + (PIANO_PANEL_H - PIANO_BTN_H) / 2)
    #define PIANO_BTN_GAP 30
    #define PIANO_BTN_REC_X ((800 - PIANO_BTN_W*4 - PIANO_BTN_GAP*3)/2)
    #define PIANO_BTN_STOP_X (PIANO_BTN_REC_X + PIANO_BTN_W + PIANO_BTN_GAP)
    #define PIANO_BTN_PLAY_X (PIANO_BTN_STOP_X + PIANO_BTN_W + PIANO_BTN_GAP)
    #define PIANO_BTN_BACK_X (PIANO_BTN_PLAY_X + PIANO_BTN_W + PIANO_BTN_GAP)
    #define KEY_VISUAL_DURATION_US 150000 // 按键按下状态的视觉持续时间（150毫秒）
    #define PIANO_PANEL_BG_COLOR 0x302C3E50 // 半透明背景
    #define PIANO_BTN_NORMAL_COLOR 0x00808080 
    #define PIANO_BTN_REC_COLOR 0xFF0000   
    #define PIANO_BTN_PLAY_COLOR 0x003498DB
    #define PIANO_BTN_PLAYING_COLOR 0x002ECC71
    #define PIANO_BTN_BACK_COLOR 0x00C0392B
    #define PIANO_BTN_TEXT_COLOR 0xFFFFFFFF 

    // --- 初始UI绘制 ---
    draw_bmp("./res/imagefiles/bg.bmp", 0, 0);
    for(int i=0; i<12; i++) draw_bmp("./res/imagefiles/key_release.bmp", 2 + i * (64 + 2), 47);
    for(int i=0; i<12; i++) draw_bmp("./res/imagefiles/key_release.bmp", 2 + i * (64 + 2), 47);
    draw_bmp("./res/imagefiles/title.bmp", 0, 0);
    lcd_draw_rect(0, PIANO_PANEL_Y, 800, PIANO_PANEL_H, PIANO_PANEL_BG_COLOR);
    int text_y_offset = (PIANO_BTN_H - 16) / 2;
    int text_x_offset = (PIANO_BTN_W - 2 * 16) / 2;
    lcd_draw_rect(PIANO_BTN_REC_X, PIANO_BTN_Y, PIANO_BTN_W, PIANO_BTN_H, PIANO_BTN_NORMAL_COLOR);
    draw_16x16(PIANO_BTN_REC_X + text_x_offset, PIANO_BTN_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xC2-0xA1)*94 + ((unsigned char)0xBC-0xA1))], PIANO_BTN_TEXT_COLOR); // 录制
    draw_16x16(PIANO_BTN_REC_X + text_x_offset + 16, PIANO_BTN_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xD6-0xA1)*94 + ((unsigned char)0xC6-0xA1))], PIANO_BTN_TEXT_COLOR);
    lcd_draw_rect(PIANO_BTN_STOP_X, PIANO_BTN_Y, PIANO_BTN_W, PIANO_BTN_H, PIANO_BTN_NORMAL_COLOR);
    draw_16x16(PIANO_BTN_STOP_X + text_x_offset, PIANO_BTN_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xCD-0xA1)*94 + ((unsigned char)0xA3-0xA1))], PIANO_BTN_TEXT_COLOR); // 停止
    draw_16x16(PIANO_BTN_STOP_X + text_x_offset + 16, PIANO_BTN_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xD6-0xA1)*94 + ((unsigned char)0xB9-0xA1))], PIANO_BTN_TEXT_COLOR);
    lcd_draw_rect(PIANO_BTN_PLAY_X, PIANO_BTN_Y, PIANO_BTN_W, PIANO_BTN_H, PIANO_BTN_PLAY_COLOR);
    draw_16x16(PIANO_BTN_PLAY_X + text_x_offset, PIANO_BTN_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xB2-0xA1)*94 + ((unsigned char)0xA5-0xA1))], PIANO_BTN_TEXT_COLOR); // 播放
    draw_16x16(PIANO_BTN_PLAY_X + text_x_offset + 16, PIANO_BTN_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xB7-0xA1)*94 + ((unsigned char)0xC5-0xA1))], PIANO_BTN_TEXT_COLOR);
    lcd_draw_rect(PIANO_BTN_BACK_X, PIANO_BTN_Y, PIANO_BTN_W, PIANO_BTN_H, PIANO_BTN_BACK_COLOR);
    draw_16x16(PIANO_BTN_BACK_X + text_x_offset, PIANO_BTN_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xB7-0xA1)*94 + ((unsigned char)0xB5-0xA1))], PIANO_BTN_TEXT_COLOR); // 返回
    draw_16x16(PIANO_BTN_BACK_X + text_x_offset + 16, PIANO_BTN_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xBB-0xA1)*94 + ((unsigned char)0xD8-0xA1))], PIANO_BTN_TEXT_COLOR);
    
    while(1) {
        long current_time_us = get_time_in_us();

        // 1. 处理按键动画：检查是否有按键需要恢复到弹起状态
        for (int i = 0; i < 12; i++) {
            if (key_release_times[i] != 0 && current_time_us >= key_release_times[i]) {
                draw_bmp("./res/imagefiles/key_release.bmp", 2 + i * (64 + 2), 47);
                key_release_times[i] = 0; // 重置时间，避免重复绘制
            }
        }

        // 2. 处理回放逻辑
        if (current_state == P_PLAYBACK) {
            int playback_finished = 0;
            if (playback_index >= note_count) {
                playback_finished = 1; // 所有音符都已播放
            } else if (current_time_us >= next_note_play_time) {
                // 时间到了，播放下一个音符
                struct NoteEvent current_note = recorded_song[playback_index];
                int key = current_note.key_index;
                play_mp3(key);
                draw_bmp("./res/imagefiles/key_press.bmp", 2 + key * (64 + 2), 47);
                key_release_times[key] = current_time_us + KEY_VISUAL_DURATION_US;
                playback_index++;
                if (playback_index < note_count) {
                    // 加上下一个音符的延迟，计算出它的播放时间
                    next_note_play_time += recorded_song[playback_index].delay_us;
                } else {
                    playback_finished = 1;
                }
            }
            if (playback_finished) {
                current_state = P_IDLE;
                // 恢复播放按钮的颜色和文字
                lcd_draw_rect(PIANO_BTN_PLAY_X, PIANO_BTN_Y, PIANO_BTN_W, PIANO_BTN_H, PIANO_BTN_PLAY_COLOR);
                draw_16x16(PIANO_BTN_PLAY_X + text_x_offset, PIANO_BTN_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xB2-0xA1)*94 + ((unsigned char)0xA5-0xA1))], PIANO_BTN_TEXT_COLOR);
                draw_16x16(PIANO_BTN_PLAY_X + text_x_offset + 16, PIANO_BTN_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xB7-0xA1)*94 + ((unsigned char)0xC5-0xA1))], PIANO_BTN_TEXT_COLOR);
            }
        }

        // 3. 处理用户输入
        fd_set readfds; struct timeval timeout; FD_ZERO(&readfds); FD_SET(fd_ts, &readfds);
        timeout.tv_sec = 0; timeout.tv_usec = 10000; // 10ms超时
        int ret = select(fd_ts + 1, &readfds, NULL, NULL, &timeout);
        if (ret > 0 && FD_ISSET(fd_ts, &readfds)) {
            struct postion pos;
            if (get_touch_event(fd_ts, &pos) == 1) {
                if (pos.y > PIANO_PANEL_Y) { // 触摸在底部控制面板
                    if (pos.x > PIANO_BTN_BACK_X && pos.x < PIANO_BTN_BACK_X + PIANO_BTN_W) { system("killall mpg123 > /dev/null 2>&1"); return; }
                    if (pos.x > PIANO_BTN_REC_X && pos.x < PIANO_BTN_REC_X + PIANO_BTN_W) { // 录制按钮
                        if (current_state == P_IDLE) {
                            current_state = P_RECORDING; note_count = 0; last_record_time = get_time_in_us();
                            lcd_draw_rect(PIANO_BTN_REC_X, PIANO_BTN_Y, PIANO_BTN_W, PIANO_BTN_H, PIANO_BTN_REC_COLOR); // 变红
                            draw_16x16(PIANO_BTN_REC_X + text_x_offset, PIANO_BTN_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xC2-0xA1)*94 + ((unsigned char)0xBC-0xA1))], PIANO_BTN_TEXT_COLOR);
                            draw_16x16(PIANO_BTN_REC_X + text_x_offset + 16, PIANO_BTN_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xD6-0xA1)*94 + ((unsigned char)0xC6-0xA1))], PIANO_BTN_TEXT_COLOR);
                        }
                    } else if (pos.x > PIANO_BTN_STOP_X && pos.x < PIANO_BTN_STOP_X + PIANO_BTN_W) { // 停止按钮
                        if (current_state == P_RECORDING) {
                            current_state = P_IDLE; // 停止录音
                            lcd_draw_rect(PIANO_BTN_REC_X, PIANO_BTN_Y, PIANO_BTN_W, PIANO_BTN_H, PIANO_BTN_NORMAL_COLOR); // 恢复颜色
                            draw_16x16(PIANO_BTN_REC_X + text_x_offset, PIANO_BTN_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xC2-0xA1)*94 + ((unsigned char)0xBC-0xA1))], PIANO_BTN_TEXT_COLOR);
                            draw_16x16(PIANO_BTN_REC_X + text_x_offset + 16, PIANO_BTN_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xD6-0xA1)*94 + ((unsigned char)0xC6-0xA1))], PIANO_BTN_TEXT_COLOR);
                        }
                    } else if (pos.x > PIANO_BTN_PLAY_X && pos.x < PIANO_BTN_PLAY_X + PIANO_BTN_W) { // 播放按钮
                        if (current_state == P_IDLE && note_count > 0) {
                            current_state = P_PLAYBACK; playback_index = 0; next_note_play_time = get_time_in_us() + recorded_song[0].delay_us;
                            lcd_draw_rect(PIANO_BTN_PLAY_X, PIANO_BTN_Y, PIANO_BTN_W, PIANO_BTN_H, PIANO_BTN_PLAYING_COLOR); // 变绿
                            draw_16x16(PIANO_BTN_PLAY_X + text_x_offset, PIANO_BTN_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xB2-0xA1)*94 + ((unsigned char)0xA5-0xA1))], PIANO_BTN_TEXT_COLOR);
                            draw_16x16(PIANO_BTN_PLAY_X + text_x_offset + 16, PIANO_BTN_Y + text_y_offset, &szHZK16[32*(((unsigned char)0xB7-0xA1)*94 + ((unsigned char)0xC5-0xA1))], PIANO_BTN_TEXT_COLOR);
                        }
                    }
                } else if (pos.y >= 47 && pos.y <= 327) { // 触摸在琴键区域
                    int key_index = pos.x / (64 + 2);
                    if (key_index >= 0 && key_index < 12) {
                        play_mp3(key_index);
                        draw_bmp("./res/imagefiles/key_press.bmp", 2 + key_index * (64 + 2), 47);
                        key_release_times[key_index] = get_time_in_us() + KEY_VISUAL_DURATION_US;
                        // 如果在录音状态，记录这个音符事件
                        if (current_state == P_RECORDING && note_count < MAX_NOTES) {
                            long current_rec_time = get_time_in_us();
                            recorded_song[note_count].key_index = key_index;
                            recorded_song[note_count].delay_us = current_rec_time - last_record_time;
                            note_count++;
                            last_record_time = current_rec_time;
                        }
                    }
                }
            }
        }
        usleep(10000); // 10ms的延时，防止CPU占用过高
    }
}
